package com.bc.commonentity.log;

import com.alibaba.dubbo.rpc.*;
import com.bc.commoncore.config.ConfigBase;
import com.bc.commoncore.util.StringUtils;
import com.bc.commonentity.enums.LogDetailType;
import com.dianping.cat.Cat;
import com.dianping.cat.message.Transaction;
import com.bc.commonentity.log.ErrorEmail;
import com.bc.commonentity.log.LogDetailHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.Map;

/**
 * Created by Administrator on 2018/4/18.
 */
public class DubboxCatFilter implements Filter {
    protected static final Logger logger = LoggerFactory.getLogger(com.bc.commonentity.log.DubboxCatFilter.class);
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation)
            throws RpcException {
        String side=invoker.getUrl().getParameter("side");
        if("provider".equals(side)){
            return aspectDubboxAccessUrl(invoker,invocation);
        }else{
            return aspectDetail(invoker,invocation);
        }
    }
    private static String getDubboxUrl(Invoker<?> invoker,Invocation invocation){
        String url=invoker.getUrl().toFullString();
        if (url!=null&&!url.isEmpty()) {
            int index=url.indexOf("?");
            if (index>0) {
                return url.substring(0, index)+"."+invocation.getMethodName();
            }else {
                return url+"."+invocation.getMethodName();
            }
        }
        return "";
    }
    private static Result aspectDetail(Invoker<?> invoker, Invocation invocation){
        if (ConfigBase.getIsOpenESLog().equals("0")) {
            return invoker.invoke(invocation);
        }
        Date beginTime=new Date();
        String resultJson="";
        String stackTrace="";
        String methodName =getDubboxUrl(invoker,invocation);
        Transaction catTrans= null;
        Map<String, String> catMessageIdsMap=null;
        try{
            //机器环境有问题时,newTransaction会引发空引用，因此这里吞掉了异常
            catTrans=Cat.newTransaction(LogDetailType.dubbox.desc(), methodName);
            catMessageIdsMap=LogDetailHelper.setAttachment(LogDetailType.dubbox);
        }catch (Exception e){
            logger.error("cat初始化失败");
        }
        try {
            Result retVal=invoker.invoke(invocation);
            if (retVal!=null) {
                //请求的返回值可能很大，会导致序列化非常耗时，因此这里注释掉
//                if(retVal.getValue()!=null){
//                    resultJson=JsonUtil.obj2string(retVal.getValue());
//                }
                if(retVal.getException()!=null){
                    throw new RuntimeException(methodName+":"+retVal.getException().getMessage(),retVal.getException());
                }
            }
            return retVal;
        }catch(Exception e){
            stackTrace=e.getMessage()+StringUtils.getStackTrace(e);
            throw e;
        }  finally {
            // 记录方法调用详细信息
            long executeTime = System.currentTimeMillis() - beginTime.getTime();
            if(catTrans!=null){
                LogDetailHelper.pigeonCall(catTrans);
                catTrans.setStatus(LogDetailHelper.getCauseBy(null,stackTrace));
                catTrans.complete();
            }
            LogDetailHelper.addLogDetail(methodName, "", invocation.getArguments(),
                    beginTime, executeTime,stackTrace, "",resultJson,LogDetailType.dubbox,catMessageIdsMap);
        }
    }
    private static Result aspectDubboxAccessUrl(Invoker<?> invoker, Invocation invocation){
        String stackTrace="";
        String resultJson="";
        String url=getDubboxUrl(invoker,invocation);
        try {
            LogDetailHelper.initCatMessageTree(url,"dubbox");
            Result retVal=invoker.invoke(invocation);
            if (retVal!=null) {
                //请求的返回值可能很大，会导致序列化非常耗时，因此这里注释掉
//                if(retVal.getValue()!=null){
//                    resultJson=JsonUtil.obj2string(retVal.getValue());
//                }
                if(retVal.getException()!=null){
                    stackTrace=retVal.getException().getMessage()+ StringUtils.getStackTrace(retVal.getException());
                }
            }
            return retVal;
        }catch(Exception e){
            stackTrace=e.getMessage()+ StringUtils.getStackTrace(e);
            throw e;
        }  finally{
            // 记录方法调用详细信息
            String clientIP = "";
            if (RpcContext.getContext()!=null) {
                clientIP = RpcContext.getContext().getRemoteHost();
            }
            String param = LogDetailHelper.getJsonParam(invocation.getArguments());
            String decryptMsg = param;
            String methodName = invoker.getInterface().getSimpleName()+"."+invocation.getMethodName();
            try{
                LogDetailHelper.systemActionLog(-1,"",0,
                        clientIP,url,param,
                        decryptMsg,"application/json;charset=utf-8","",
                        "POST",methodName,resultJson,
                        stackTrace,"dubboxAccessUrl");
            }catch (Exception e){
                logger.error(url+"aspectDubboxAccessUrl时出错:"+e.getMessage()+StringUtils.getStackTrace(e));
                ErrorEmail.sendErrorMail(url+"aspectDubboxAccessUrl时出错",e);
            }
        }
    }
}
